package com.bytebuddytest.custominstrumentation;

import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.jar.asm.MethodVisitor;

/**
 * @author yutianhong
 * @version 1.0
 * @since 2023/12/28 16:41
 */
public enum SumMethod implements ByteCodeAppender {

    INSTANCE; // singleton

    @Override
    public Size apply(MethodVisitor methodVisitor,
                      Implementation.Context implementationContext,
                      MethodDescription instrumentedMethod) {
        if (!instrumentedMethod.getReturnType().asErasure().represents(int.class)) {
            throw new IllegalArgumentException(instrumentedMethod + " must return int");
        }
        StackManipulation.Size operandStackSize = new StackManipulation.Compound(
                IntegerConstant.forValue(10),
                IntegerConstant.forValue(50),
                IntegerSum.INSTANCE,
                MethodReturn.INTEGER
        ).apply(methodVisitor, implementationContext);
        // 方法操作数栈深度：取operandStackSize的操作数栈最大深度
        // 方法的局部变量表大小：由于这个方法没有涉及自定义的局部变量，所以只取决于方法入参、this对象引用
        return new Size(operandStackSize.getMaximalSize(),
                instrumentedMethod.getStackSize());
    }
}
